import { useEffect, useRef, useState } from 'react'
import styles from './style.module.scss'
// import pianoSvg from '@/assets/svg/piano.svg'
import EventEmitter from '../EventEmitter'
import { showToast } from '../toast'
import { t } from '@/i18n'
// import pianoSvg from '@/assets/svg/piano.svg'
const defaultTimeout = 1000 * 60 * 30
type LoadingEvent = {
  showLoading: (
    text: string,
    timeout: number,
    fnRef: { close: CloseLoadingFn | null; setProgress: SetProgressFn },
    timeOutText?: string
  ) => void
}
interface CloseLoadingFn {
  /**
   * waitTask需要等待的任务并且返回值
   */
  <T>(waitTask: Promise<T>): Promise<T>
  (): void
}
interface SetProgressFn {
  (progress: number): void
}
enum TypeLoadingState {
  loading,
  success,
  timeout,
}
const emit = new EventEmitter<LoadingEvent>()
let isUseToast = false
const Loading = () => {
  const [loading, setLoading] = useState(false)
  const [loadingText, setLoadingText] = useState('加载中')
  const [progress, setProgress] = useState(0)
  const loadingVersion = useRef(0)

  useEffect(() => {
    if (isUseToast) {
      console.warn('loading组件已存在，请勿重复使用')
    }
    emit.on('showLoading', (text, timeOut, fnRef, timeOutText) => {
      setLoading(true)
      setProgress(0)
      setLoadingText(text)
      const currentVersion = ++loadingVersion.current
      let loadingState = TypeLoadingState.loading
      const timer = setTimeout(() => {
        if (currentVersion !== loadingVersion.current) return
        if (loadingState !== TypeLoadingState.loading) return
        loadingState = TypeLoadingState.timeout
        setLoading((loading) => {
          if (loading) {
            loadingVersion.current++
            showToast(timeOutText || `加载超时`)
          }
          setProgress(0)
          return false
        })
      }, timeOut)
      // @ts-ignore
      fnRef.close = (task?: Promise<any>) => {
        const close = () => {
          if (currentVersion !== loadingVersion.current) return
          if (loadingState !== TypeLoadingState.loading) return
          loadingState = TypeLoadingState.success
          clearTimeout(timer)
          setLoading(false)
          setProgress(0)
        }
        if (task) {
          return task.finally(close)
        }
        close()
      }
      fnRef.setProgress = (progress: number) => {
        if (currentVersion !== loadingVersion.current) return
        if (loadingState !== TypeLoadingState.loading) return
        setProgress(Math.min(progress, 100))
      }
    })
    isUseToast = true
    return () => {
      isUseToast = false
    }
  }, [])
  if (!loading) {
    return <></>
  }
  return (
    <>
      <div className={styles['loading-component-mask']}></div>
      <div className={styles['loading-component-view']}>
        <div className={styles['logo-view']}>
          {/* <img src={pianoSvg} className={styles['logo']} /> */}
          {/* <div className={styles['mask-cube']}></div> */}
          <div className={styles['lds-roller']}>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
          </div>
        </div>
        <div className={styles['tips']}>{loadingText}</div>
        {progress != 0 && (
          <progress
            style={{
              width: '80%',
              marginBottom: 5,
              accentColor: 'var(--primary-color)',
            }}
            max={100}
            value={progress}></progress>
        )}
      </div>
    </>
  )
}
export default function useLoading() {
  return { Loading, showLoading }
}
/**
 *
 * @param text loading文字
 * @param timeout 默认10秒
 * @param timeOutText 超时提示文字
 * @returns closeLoading
 */
export function showLoading(
  text = t('loading'),
  timeout: number = defaultTimeout,
  timeOutText?: string
) {
  if (!isUseToast) {
    throw new Error('loading组件未使用，请使用useLoading')
  }
  const closeFnRef = {
    close: null as CloseLoadingFn | null,
    setProgress: null as SetProgressFn | null,
  }

  emit.emit('showLoading', text, timeout, closeFnRef, timeOutText)

  const handle = closeFnRef.close! as LoadingHandler
  handle.setProgress = closeFnRef.setProgress!
  return handle
}

interface LoadingHandler {
  /**
   * waitTask需要等待的任务并且返回值
   */
  <T>(waitTask: Promise<T>): Promise<T>
  (): void
  setProgress: SetProgressFn
}
